package chapter07._02_CatchException;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * @Description: finally子句的练习
 * @LastDate: 2020/10/22
 */
public class Test04_Finally {

    public static void main(String[] args) throws IOException {
        /*
        * 此处展示一种功能性更强的写法
        * 外层的try：负责报告出现的错误
        * 内存的try-finally：负责关闭资源
        * 且这种写法 还会报告内存try的catch和finally语句出现的异常
        * */
        var in = new FileInputStream("filename");
        try {
            try {
                int b;
                while ((b = in.read()) != -1) {
                    //do something
                }
            } finally {
                in.close();
            }
        } catch (IOException e) {
            throw e;
        }
    }

    /*
    * 什么是finally子句？
    * 衔接在捕捉异常的语句try-catch最后 做完try/catch之后一定会做的语句块
    * 最常用于关闭资源
    * 现在有更好的语句try-with-resources来关闭资源
    * */
    public void readWithThrowAgain(String fileName) throws IOException {
        /*
        * 在这个例子中，可能在3种情况执行finally语句
        * 1. 代码每天抛出异常 执行try全部代码 1->2->5->6
        * 2. 代码抛出异常 并且是catch语句中异常 成功被catch
        *    如果catch中也没有异常 则 1->3->4->5->6
        *    如果catch中也有异常 则 1->3->5->6
        * 3. 代码抛出异常 但是没有被catch 此时会直接跳转finally 1->5->6
        *
        * Notes:
        *       1.try可以没有catch 可以只有finally
        *       2.try-catch-finally可以嵌套
        * 总结：无论有无异常 finally都会被执行
        * */
        var in = new FileInputStream(fileName);
        try {
            //1
            int b;
            while ((b = in.read()) != -1) {
                //do something
            }
            //2
        } catch (IOException e) {
            /*
             * 可以不对异常进行操作 再次throw
             * */
            //3
            throw e;
            //4
        } finally {
            //5
            in.close();
            //6
        }
    }

    /*Warning
    * 编程就是这么狗血
    * 如果在finally语句包含return
    * 不管前面return什么值
    * 最后都会被finally的return覆盖
    * 有时候finally的return甚至会把异常吞掉
    * 所以finally必须只用来回收资源
    * 会改变语句顺序的语句 如return break continue throw 都不要放在里面
    * */
}
